
package com.epam.android.training.day6.task2;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import java.util.HashMap;

/**
 * Provides access to a database of contact names. Each name entry has a contact
 * first name and contact last name.
 * 
 * @author Anton Novikov
 */
public class ContactsProvider extends ContentProvider {

  private static final String TAG = ContactsProvider.class.getSimpleName();

  private static final String DATABASE_NAME = "my_contacts.db";

  private static final int DATABASE_VERSION = 1;

  private static final String NAMES_TABLE_NAME = "names";

  private static HashMap<String, String> contactNameProjectionMap;

  private DatabaseHelper dbHelper;

  static {
    contactNameProjectionMap = new HashMap<String, String>();
    contactNameProjectionMap.put(Contacts.Names._ID, Contacts.Names._ID);
    contactNameProjectionMap.put(Contacts.Names.FIRST_NAME, Contacts.Names.FIRST_NAME);
    contactNameProjectionMap.put(Contacts.Names.LAST_NAME, Contacts.Names.LAST_NAME);
  }

  @Override
  public boolean onCreate() {
    dbHelper = new DatabaseHelper(getContext());
    return true;
  }

  @Override
  public Cursor query(final Uri uri, final String[] projection, final String selection,
      final String[] selectionArgs, final String sortOrder) {
    final SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    queryBuilder.setTables(NAMES_TABLE_NAME);

    // supports only one table, there is no need of uri matcher
    queryBuilder.setProjectionMap(contactNameProjectionMap);

    // If no sort order is specified use the default
    String orderBy;
    if (TextUtils.isEmpty(sortOrder)) {
      orderBy = Contacts.Names.DEFAULT_SORT_ORDER;
    } else {
      orderBy = sortOrder;
    }

    // Get the database and run the query
    final SQLiteDatabase db = dbHelper.getReadableDatabase();
    final Cursor c = queryBuilder.query(db, projection, selection, selectionArgs, null, null,
        orderBy);

    // Tell the cursor what uri to watch, so it knows when its source data
    // changes
    c.setNotificationUri(getContext().getContentResolver(), uri);
    return c;
  }

  @Override
  public String getType(final Uri uri) {
    if (uri != null) {
      return Contacts.Names.CONTENT_TYPE;
    } else {
      throw new IllegalArgumentException("URI is not provided.");
    }
  }

  @Override
  public Uri insert(final Uri uri, final ContentValues initialValues) {
    // Validate the requested uri
    if (uri == null) {
      throw new IllegalArgumentException("URI is not provided.");
    }

    ContentValues values;
    if (initialValues != null) {
      values = new ContentValues(initialValues);
    } else {
      values = new ContentValues();
    }
    // Make sure that the fields are all set
    if (!values.containsKey(Contacts.Names.FIRST_NAME)) {
      values.put(Contacts.Names.FIRST_NAME, "");
    }
    if (!values.containsKey(Contacts.Names.LAST_NAME)) {
      values.put(Contacts.Names.LAST_NAME, "");
    }

    final SQLiteDatabase db = dbHelper.getWritableDatabase();
    final long rowId = db.insert(NAMES_TABLE_NAME, Contacts.Names.FIRST_NAME, values);

    if (rowId > 0) {
      final Uri noteUri = ContentUris.withAppendedId(Contacts.Names.CONTENT_URI, rowId);
      getContext().getContentResolver().notifyChange(noteUri, null);
      return noteUri;
    }

    throw new SQLException("Failed to insert row into " + uri);
  }

  @Override
  public int delete(final Uri uri, final String selection, final String[] selectionArgs) {
    final SQLiteDatabase db = dbHelper.getWritableDatabase();
    final int count = db.delete(NAMES_TABLE_NAME, selection, selectionArgs);
    getContext().getContentResolver().notifyChange(uri, null);
    return count;
  }

  @Override
  public int update(final Uri uri, final ContentValues values, final String selection,
      final String[] selectionArgs) {
    final SQLiteDatabase db = dbHelper.getWritableDatabase();
    final int count = db.update(NAMES_TABLE_NAME, values, selection, selectionArgs);
    getContext().getContentResolver().notifyChange(uri, null);
    return count;
  }

  /**
   * This class helps open, create, and upgrade the database file.
   * 
   * @author Anton Novikov
   */
  private static class DatabaseHelper extends SQLiteOpenHelper {

    public DatabaseHelper(final Context context) {
      super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(final SQLiteDatabase db) {
      db.execSQL("CREATE TABLE " + NAMES_TABLE_NAME + " (" + Contacts.Names._ID
          + " INTEGER PRIMARY KEY," + Contacts.Names.FIRST_NAME + " TEXT,"
          + Contacts.Names.LAST_NAME + " TEXT" + ");");
    }

    @Override
    public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
      Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion
          + ", which will destroy all old data");
      db.execSQL("DROP TABLE IF EXISTS names");
      onCreate(db);
    }
  }
}
